using System;
using System.Runtime.CompilerServices;

namespace UtilZ.Dotnet.Ex.Base
{
    /// <summary>
    /// Math扩展类
    /// </summary>
    unsafe public partial class MathEx
    {
        /// <summary>
        /// double0
        /// </summary>
        public const double ZERO_D = 0d;

        /// <summary>
        /// int0
        /// </summary>
        public const int ZERO_I = 0;

        /// <summary>
        /// 角度0°
        /// </summary>
        public const double ANGLE_0 = 0d;

        /// <summary>
        /// 角度90°
        /// </summary>
        public const double ANGLE_90 = 90d;

        /// <summary>
        /// 角度180°
        /// </summary>
        public const double ANGLE_180 = 180d;

        /// <summary>
        /// 角度270°
        /// </summary>
        public const double ANGLE_270 = 270d;

        /// <summary>
        /// 角度360°
        /// </summary>
        public const double ANGLE_360 = 360d;

        /// <summary>
        /// 角度转换为弧度
        /// </summary>
        /// <param name="angle">角度</param>
        /// <returns></returns>
        public static double AngleToRadians(double angle)
        {
            return angle * Math.PI / ANGLE_180;
        }

        /// <summary>
        /// 弧度转换为角度
        /// </summary>
        /// <param name="radians">弧度</param>
        /// <returns></returns>
        public static double RadiansToAngle(double radians)
        {
            return radians * ANGLE_180 / Math.PI;
        }

        /// <summary>
        /// 将角度值转换为0-360°
        /// </summary>
        /// <param name="angle">角度值</param>
        /// <returns>角度值</returns>
        public static double AbsAngle(double angle)
        {
            if (angle < ZERO_D || angle - ANGLE_360 >= ZERO_D)
            {
                angle = angle % ANGLE_360;
                if (angle < ZERO_D)
                {
                    angle += ANGLE_360;
                }
            }

            return angle;
        }

        /// <summary>
        /// 获取指定角度所在象限
        /// </summary>
        /// <param name="angle">角度</param>
        /// <returns>角度所在象限</returns>
        public static Quadrant GetQuadrantByAngle(double angle)
        {
            angle = AbsAngle(angle);
            Quadrant quadrant;
            if (angle - ANGLE_270 > ZERO_D)
            {
                //360°>angle>270°
                quadrant = Quadrant.Four;
            }
            else if (angle - ANGLE_270 == ZERO_D)
            {
                //angle=270°
                quadrant = Quadrant.NegativeYAxisAngle;
            }
            else if (angle - ANGLE_180 > ZERO_D)
            {
                //270°>angle>180°
                quadrant = Quadrant.Three;
            }
            else if (angle - ANGLE_180 == ZERO_D)
            {
                //angle=180°
                quadrant = Quadrant.NegativeXAxisAngle;
            }
            else if (angle - ANGLE_90 > ZERO_D)
            {
                //180°>angle>90°
                quadrant = Quadrant.Two;
            }
            else if (angle - ANGLE_90 == ZERO_D)
            {
                //angle=90°
                quadrant = Quadrant.PositiveYAxisAngle;
            }
            else if (angle - ANGLE_0 > ZERO_D)
            {
                //90°>angle>0°
                quadrant = Quadrant.One;
            }
            else
            {
                //angle=0°
                quadrant = Quadrant.PositiveXAxisAngle;
            }

            return quadrant;
        }


        /*
        /// <summary>
        /// 计算指定坐标点围绕中心点旋转指定角度后的坐标
        /// </summary>
        /// <param name="center">中心点</param>
        /// <param name="p">旋转点</param>
        /// <param name="angle">旋转角度</param>
        /// <returns>旋转后的坐标</returns>
        public static object PointRotate(double cx, double cy, double px, double py, double angle)
        {
            //先计算p相对center为中心所在象限,再计算p-c之间的角度,再根据象限以及旋转的解译算出旋转后的坐标
            throw new NotImplementedException("以后有空再来算");

            //double angleHude = angle * Math.PI / 180;//角度转弧度
            //double x1 = (p.X - center.X) * Math.Cos(angleHude) + (p.Y - center.Y) * Math.Sin(angleHude) + center.X;
            //double y1 = -(p.X - center.X) * Math.Sin(angleHude) + (p.Y - center.Y) * Math.Cos(angleHude) + center.Y;
            //return new PointF((float)x1, (float)y1);
        }*/





        /// <summary>
        /// 求两个数的最小公倍数
        /// </summary>
        /// <param name="a">第一个整数</param>
        /// <param name="b">第二个整数</param>
        /// <returns>最小公倍数</returns>
        public static int LCM(int a, int b)
        {
            return a * b / GCD(a, b);
        }

        /// <summary>
        /// 求两个数的最大公约数
        /// </summary>
        /// <param name="a">第一个整数</param>
        /// <param name="b">第二个整数</param>
        /// <returns>最大公约数</returns>
        public static int GCD(int a, int b)
        {
            if (a == b)
            {
                return a;
            }

            int mod;
            while (true)
            {
                if (a < b)
                {
                    mod = b % a;
                    if (mod == 0)
                    {
                        return a;
                    }
                    else
                    {
                        b = mod;
                    }
                }
                else
                {
                    mod = a % b;
                    if (mod == 0)
                    {
                        return b;
                    }
                    else
                    {
                        a = mod;
                    }
                }
            }


            //if (a < b)
            //{
            //    a = a + b;
            //    b = a - b;
            //    a = a - b;
            //}

            //if (a % b == 0)
            //{
            //    return b;
            //}
            //else
            //{
            //    return MAXGY(a % b, b);
            //}
        }


#if CORE
        /// <summary>
        /// 获取浮点数的小数位数
        /// </summary>
        /// <param name="value">浮点数</param>
        /// <returns>小数位数</returns>
        public static int GetDigits(Half value)
        {
            string preStr = value.ToString();
            return preStr.Length - preStr.IndexOf('.') - 1;
        }
#endif

        /// <summary>
        /// 获取浮点数的小数位数
        /// </summary>
        /// <param name="value">浮点数</param>
        /// <returns>小数位数</returns>
        public static int GetDigits(double value)
        {
            string preStr = value.ToString();
            return preStr.Length - preStr.IndexOf('.') - 1;
        }

        /// <summary>
        /// 获取浮点数的小数位数
        /// </summary>
        /// <param name="value">浮点数</param>
        /// <returns>小数位数</returns>
        public static int GetDigits(float value)
        {
            string preStr = value.ToString();
            return preStr.Length - preStr.IndexOf('.') - 1;
        }

        /// <summary>
        /// 获取浮点数的小数位数
        /// </summary>
        /// <param name="value">浮点数</param>
        /// <returns>小数位数</returns>
        public static int GetDigits(decimal value)
        {
            string preStr = value.ToString();
            return preStr.Length - preStr.IndexOf('.') - 1;
        }




        /// <summary>
        /// 判断指定数是否为奇数,为奇数返回true,为偶数返回false
        /// </summary>
        /// <param name="value">用于判断的数</param>
        /// <returns>为奇数返回true,为偶数返回false</returns>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public static bool IsOddInteger(int value)
        {
            /************************************************
             *   00011001        00011000
             * & 00000001      & 00000001
             * -----------     -----------
             *   00000001        00000000
             ************************************************/
            if ((value & 1) == 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 判断指定数是否为偶数,为偶数返回true,为奇数返回false
        /// </summary>
        /// <param name="value">用于判断的数</param>
        /// <returns>为偶数返回true,为奇数返回false</returns>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public static bool IsEvenInteger(int value)
        {
            /************************************************
             *   00011001        00011000
             * & 00000001      & 00000001
             * -----------     -----------
             *   00000001        00000000
             ************************************************/
            if ((value & 1) == 1)
            {
                return false;
            }
            else
            {
                return true;
            }
        }


    }




    /// <summary>
    /// XY坐标系象限类型枚举
    /// </summary>
    public enum Quadrant
    {
        /// <summary>
        /// 正X轴轴线角,即0°角
        /// </summary>
        PositiveXAxisAngle,

        /// <summary>
        /// <![CDATA[第一象限(x>0,y>0)]]>
        /// </summary>
        One,

        /// <summary>
        /// 正Y轴轴线角,即90°角
        /// </summary>
        PositiveYAxisAngle,

        /// <summary>
        /// <![CDATA[第二象限(x<0,y>0)]]>
        /// </summary>
        Two,

        /// <summary>
        /// 负X轴轴线角,即180°角
        /// </summary>
        NegativeXAxisAngle,

        /// <summary>
        /// <![CDATA[第三象限(x<0,y<0)]]>
        /// </summary>
        Three,

        /// <summary>
        /// 负Y轴轴线角,即270°角
        /// </summary>
        NegativeYAxisAngle,

        /// <summary>
        /// <![CDATA[第四象限(x>0,y<0)]]>
        /// </summary>
        Four
    }
}
